<template>
  <tableLayout :columns="columns" :get="getData" ref="layout" :rules="rules" :selectItem="selectItem"
    :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }">
    <template v-slot:status="item">
      测试-{{ item.value.text.name }}
    </template>
    <template #button>
      <a-button type="primary" style="margin-left: 20px" @click='add'>新增</a-button>
      <a-button style="margin-left: 20px" @click="edit" :disabled="selectedRowKeys.length !== 1">修改</a-button>
      <a-button type="primary" style="margin-left: 20px" danger @click="del"
        :disabled="selectedRowKeys.length !== 1">删除</a-button>
    </template>
    <template #operationMore="item">
      <a @click="edit(null, item.value.record)">编辑</a>
      <a-divider type="vertical" />
      <a @click="del(null, item.value.record.Id)">删除</a>
    </template>

    <template v-slot:custom="data">
      <a-input v-model:value="data.formData[data.key]" />
    </template>
  </tableLayout>
  <a-modal :title="formState.Id ? '编辑角色' : '新增角色'" v-model:visible="model_visible" :confirm-loading="confirmLoading"
    @ok="model_handleOk" width="900px">
    <a-form ref="formRef" :model="formState" :label-col="labelCol" :wrapper-col="wrapperCol" :rules="rules"
      layout="inline" class="comform">
      <a-form-item label="名称" style="width: calc(50% - 20px);" class="form__item" name="Name">
        <a-input v-model:value="formState.Name" />
      </a-form-item>
      <a-form-item label="键" style="width: calc(50% - 20px);" class="form__item" name="Key">
        <a-input v-model:value="formState.Key" />
      </a-form-item>

      <a-form-item label="备注" style="width: calc(100% - 20px);" class="form__item" name="Remark" :labelCol="{ span: 3 }"
        :wrapperCol="{ span: 21 }">
        <a-textarea v-model:value="formState.Remark" placeholder="备注" :rows="4" />
      </a-form-item>
      <a-form-item label="是否管理员" style="width: calc(50% - 20px);" class="form__item" name="IsSys">
        <a-checkbox v-model:checked="formState.IsSys">
        </a-checkbox>
      </a-form-item>
      <a-form-item label="菜单" style="width: calc(100% - 20px);height:250px;" class="form__item" name="MenuIdList"
        :labelCol="{ span: 3 }" :wrapperCol="{ span: 21 }">
        <a-transfer class="menuTransfer" :data-source="transferMenuData" show-search :rowKey="record => record.Id"
          :filter-option="filterMenuOption" :target-keys="formState.MenuIdList" :render="item => item.Name"
          @change="handleMenuChange" @search="handleMenuSearch">
          <template #children="{ direction, selectedKeys, onItemSelect }">
            <a-tree style="height: 150px;overflow:auto;" v-if="direction === 'left'" blockNode checkable checkStrictly
              defaultExpandAll :checkedKeys="[...selectedKeys, ...formState.MenuIdList]"
              :replaceFields="{ children: 'children', title: 'Name', key: 'Id' }" :treeData="treeData" @check="(_, props) => {
                onChecked(_, props, [...selectedKeys, ...formState.MenuIdList], onItemSelect);
              }
              " @select="(_, props) => {
                  onChecked(_, props, [...selectedKeys, ...formState.MenuIdList], onItemSelect);
                }
                " />
          </template>
        </a-transfer>
      </a-form-item>
      <a-form-item label="资源" style="width: calc(100% - 20px);" class="form__item" name="ApiIdList"
        :labelCol="{ span: 3 }" :wrapperCol="{ span: 21 }">
        <a-transfer :data-source="transferApiData" show-search :rowKey="record => record.Id"
          :filter-option="filterApiOption" :target-keys="formState.ApiIdList" :render="item => item.ControllerName"
          @change="handleApiChange" @search="handleApiSearch"></a-transfer>
      </a-form-item>
    </a-form>
  </a-modal>
</template>

<script lang="ts">
import { defineComponent, computed, ref, onMounted, onBeforeMount, nextTick, UnwrapRef, reactive, h, VNode } from 'vue';
import tableLayout from '@/components/tableLayout/tableLayout.vue';
import { getData, setRole, delRole, getMenuTreeData, getApiData, getRoleInfo } from '@/api/syssetting/role';
import { RoleInput } from '@/types/api/syssetting/role';
import { Layout, message } from 'ant-design-vue';
import { text } from 'stream/consumers';

export default defineComponent({
  name: 'sys_role',
  components: {
    tableLayout
  },
  setup() {
    const layout = ref();

    const transferApiData = ref([]);
    const transferMenuData = ref([]);
    let menuData = {};
    const flatten = (list: any[] = []) => {
      list.forEach(item => {
        transferMenuData.value.push(item);
        if (item.children)
          flatten(item.children);
      });
    }

    onMounted(() => {

      getMenuTreeData({}).then(e => {
        menuData = e.data.Data;
        flatten(e.data.Data);
      }).catch(err => {
        message.error(err.message || "获取菜单失败!")
      });

      getApiData({}).then(e => {
        transferApiData.value = e.data.Data;

      }).catch(err => {
        message.error(err.message || "获取资源失败!")
      });

    })

    const onChange = (keys: any[]) => {
      formState.MenuIdList = keys;
    };

    const isChecked = (selectedKeys: any[], eventKey: string) => {
      return selectedKeys.indexOf(eventKey) !== -1;
    }

    const onChecked = (
      _: Record<any, any[]>,
      e: CheckEvent,
      checkedKeys: any[],
      onItemSelect: (n: any, c: boolean) => void,
    ) => {
      const { eventKey } = e.node;
      onItemSelect(eventKey, !isChecked(checkedKeys, eventKey));
    };

    const treeData = computed<any[]>(() => {
      return handleTreeData(menuData, formState.MenuIdList);
    });

    const handleTreeData = (data: any[], targetKeys: any[] = []) => {

      data.forEach(item => {
        //item['disabled'] = targetKeys.includes(item.Id);
        if (item.children) {
          handleTreeData(item.children, targetKeys);
        }
      });

      return data;
    }

    //列表
    const columns = [
      { title: '序号', dataIndex: 'Id' },
      { title: '名称', dataIndex: 'Name' },
      {
        title: '是否管理员', dataIndex: 'IsSys', customRender: function ({ text }): VNode {
          return h('div', {
            style: {
              color: 'red'
            }
          }, text ? '是' : '否');
        }
      },

      { title: '创建时间', dataIndex: 'CreateTime' }
    ]

    // 筛选
    const selectItem = ref([
      { title: '名称', key: 'Name', type: 'input', itemWidth: '290px' },
      { title: '键', key: 'Key', type: 'input', itemWidth: '290px' }
    ]);

    // 规则
    const rules = {
      Name: [{ required: true, message: '请输入名称', trigger: 'change' }],
      Key: [{ required: true, message: '请输入键', trigger: 'change' }]
    }

    //表单对象
    const formState: UnwrapRef<RoleInput> = reactive({
      Id: 0,
      PlatformKey: "",
      Key: "",
      Name: "",
      Remark: "",
      IsSys: false,
      MenuIdList: [],
      ApiIdList: []
    });

    const add = () => {
      model_visible.value = true;
      Object.assign(formState, {
        Id: 0,
        PlatformKey: '',
        Key: '',
        Name: '',
        Remark: '',
        IsSys: false,
        MenuIdList: [],
        ApiIdList: []
      });
    }

    const edit = (event: any, item: any) => {
      let selectItem = item;
      if (!selectItem) {
        if (!selectedRowKeys.value || selectedRowKeys.value.length <= 0 || selectedRowKeys.value.length > 1) {
          message.warning('请先选择一条数据!');
          return;
        }
        selectItem = selectedRows.value[0];
      }
      model_visible.value = true;
      Object.assign(formState, selectItem);

      getRoleInfo({ RoleId: selectItem.Id }).then(e => {
        formState.MenuIdList = e.data.Data.MenuList;
        formState.ApiIdList = e.data.Data.ApiList;
      }).catch(err => {
        message.error(err.message || "获取角色信息失败!")
      })
    }

    const del = (event: any, id: any) => {
      let selectId = id;
      if (!selectId) {
        if (!selectedRowKeys.value || selectedRowKeys.value.length <= 0 || selectedRowKeys.value.length > 1) {
          message.warning('请先选择一条数据!');
          return;
        }
        selectId = selectedRowKeys.value[0];
      }

      delRole({ Id: selectId }).then(() => {
        message.success("删除成功!");
        layout.value.getData();
      }).catch(err => {
        message.error(err.message || "删除失败!")
        confirmLoading.value = false;
      })
    }

    //穿梭框过滤
    const filterApiOption = (inputValue: string, option: any) => {
      return option.ControllerName.indexOf(inputValue) > -1;
    };

    //穿梭框数据搜索
    const handleApiSearch = (dir: string, value: string) => {
      // console.log('search:', dir, value);
    };
    //穿梭框数据处理数据
    const handleApiChange = (keys: Number[], direction: string, moveKeys: string[]) => {
      // console.log(keys, direction, moveKeys);
      formState.ApiIdList = keys;
    };

    //穿梭框过滤
    const filterMenuOption = (inputValue: string, option: any) => {
      return option.Name.indexOf(inputValue) > -1;
    };

    //穿梭框数据搜索
    const handleMenuSearch = (dir: string, value: string) => {
      // console.log('search:', dir, value);
    };
    //穿梭框数据处理数据
    const handleMenuChange = (keys: Number[], direction: string, moveKeys: string[]) => {
      // console.log(keys, direction, moveKeys);
      formState.MenuIdList = keys;
    };
    const model_visible = ref<boolean>(false);
    const confirmLoading = ref<boolean>(false);
    const formRef = ref()

    const model_handleOk = () => {
      formRef.value.validate().then(() => {
        confirmLoading.value = true;
        setRole(formState).then(e => {
          if(formState.Id == 0){
            message.success("添加成功！");
          }else{
            message.success("修改成功！");
          }
          
          confirmLoading.value = false;
          model_visible.value = false;
          layout.value.getData();
        }).catch(err => {
          message.error(err.message || "添加失败!")
          confirmLoading.value = false;
        })
      }).catch(() => {
        message.error('请检查必填项是否全部填写!');
      })
    }

    // 多选
    const selectedRowKeys = ref<any[]>([]);
    const selectedRows = ref<any[]>([]);
    const onSelectChange = (keys: [], rows: any) => {
      selectedRowKeys.value = keys;
      selectedRows.value = rows;
    }


    const labelCol = { span: 6 };
    const wrapperCol = { span: 18 };

    return {
      columns, labelCol, wrapperCol, getData, selectItem, layout, rules, formState,
      selectedRowKeys, onSelectChange, model_visible, confirmLoading, add, edit, del, model_handleOk, formRef,
      transferApiData, transferMenuData, handleApiChange, handleApiSearch, filterApiOption, handleMenuChange, handleMenuSearch,
      filterMenuOption, treeData, onChecked, onChange, isChecked
    }
  }
})
</script>

<style lang="scss" scoped>
.comform {
  & .form__item {
    margin-bottom: 16px;

    & .ant-form-item-label {
      flex-grow: 1 !important;
      flex-shrink: 0;
    }
  }
}

.tree-transfer .ant-transfer-list:first-child {
  width: 50%;
  flex: none;
}

.menuTransfer .ant-transfer-list-content {
  height: 150px;
  overflow: auto;
}

.ant-transfer-list {
  width: calc(50% - 20px) !important;
}
</style>
<style lang="scss">
.comform {
  & .form__item {
    margin-bottom: 16px;

    & .ant-form-item-label {
      flex-grow: 1;
      flex-shrink: 0;
    }
  }
}

.ant-transfer-list {
  width: calc(50% - 20px) !important;
}

.tree-transfer .ant-transfer-list:first-child {
  width: 50%;
  flex: none;
}

.menuTransfer .ant-transfer-list-content {
  height: 150px;
  overflow: auto;
}
</style>
